﻿using ConsoleTest.LinqToSql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleTest
{
    // <summary>
    /// 根据Expression表达式生成SQL-Where部分的语句
    /// </summary>
    public class LambdaToSql
    {
        #region Expression 转成 where
        /// <summary>
        /// Expression 转成 Where String
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="predicate"></param>
        /// <param name="databaseType">数据类型（用于字段是否加引号）</param>
        /// <returns></returns>
        public static string GetWhereByLambda<T>(Expression<Func<T, bool>> predicate, string databaseType = "SqlServer")
        {
            bool withQuotationMarks = GetWithQuotationMarks(databaseType);
            ConditionBuilder conditionBuilder = new ConditionBuilder();
            conditionBuilder.SetIfWithQuotationMarks(withQuotationMarks); //字段是否加引号（PostGreSql,Oracle）
            conditionBuilder.SetDataBaseType(databaseType);
            conditionBuilder.Build(predicate);

            object ce = null;
            for (int i = 0; i < conditionBuilder.Arguments.Length; i++)
            {
                ce = conditionBuilder.Arguments[i];
                if (ce == null)
                {
                    conditionBuilder.Arguments[i] = DBNull.Value;
                    continue;
                }
                if (ce is string || ce is char)
                {
                    bool isQuote = ce.ToString().ToLower().Trim().IndexOf(@"in(") == 0 ||
                        ce.ToString().ToLower().Trim().IndexOf(@"not in(") == 0 ||
                        ce.ToString().ToLower().Trim().IndexOf(@" like '") == 0 ||
                        ce.ToString().ToLower().Trim().IndexOf(@"not like") == 0;
                    conditionBuilder.Arguments[i] = string.Format(" {1}{0}{2} ", ce.ToString(), isQuote ? "" : "'", isQuote ? "" : "'");
                    continue;
                }
                if (ce is int || ce is long || ce is short || ce is decimal || ce is double || ce is float || ce is bool || ce is byte || ce is sbyte || ce is ValueType)
                {
                    conditionBuilder.Arguments[i] = ce.ToString();
                    continue;
                }
                conditionBuilder.Arguments[i] = string.Format("'{0}'", ce.ToString());
            }
            return string.Format(conditionBuilder.Condition, conditionBuilder.Arguments);
        }

        /// <summary>
        /// 获取是否字段加双引号
        /// </summary>
        /// <param name="databaseType"></param>
        /// <returns></returns>
        public static bool GetWithQuotationMarks(string databaseType)
        {
            bool result = false;
            switch (databaseType.ToLower())
            {
                case DataBaseType.PostGreSql:
                case DataBaseType.Oracle:
                    result = true;
                    break;
            }
            return result;
        }
        #endregion
    }
}
